/**
 * @file instruction.h
 * @brief VimL虚拟机指令集定义
 * @author VimLVM Team
 * @date 2025
 */

#ifndef VIML_INSTRUCTION_H
#define VIML_INSTRUCTION_H

#include "common.h"
#include <vector>

namespace viml {

// 操作码定义
enum class OpCode : uint8_t {
    // 常量操作
    LOAD_CONST,      // 加载常量到寄存器
    LOAD_NIL,        // 加载nil到寄存器
    LOAD_TRUE,       // 加载true到寄存器
    LOAD_FALSE,      // 加载false到寄存器
    
    // 寄存器操作
    MOVE,            // 寄存器间移动
    
    // 算术运算
    ADD,             // 加法
    SUB,             // 减法
    MUL,             // 乘法
    DIV,             // 除法
    MOD,             // 取模
    NEG,             // 取负
    
    // 逻辑运算
    AND,             // 逻辑与
    OR,              // 逻辑或
    NOT,             // 逻辑非
    
    // 比较运算
    EQ,              // 等于
    NE,              // 不等于
    LT,              // 小于
    LE,              // 小于等于
    GT,              // 大于
    GE,              // 大于等于
    
    // 跳转
    JMP,             // 无条件跳转
    JMP_IF_TRUE,     // 为真时跳转
    JMP_IF_FALSE,    // 为假时跳转
    
    // 函数调用
    CALL,            // 函数调用
    RETURN_OP,       // 函数返回
    
    // 作用域操作
    LOAD_GLOBAL,     // 加载全局变量
    STORE_GLOBAL,    // 存储全局变量
    LOAD_LOCAL,      // 加载局部变量
    STORE_LOCAL,     // 存储局部变量
    LOAD_UPVALUE,    // 加载上值
    STORE_UPVALUE,   // 存储上值
    
    // 集合操作
    NEW_LIST,        // 创建列表
    NEW_DICT,        // 创建字典
    GET_INDEX,       // 获取索引
    SET_INDEX,       // 设置索引
    LEN,             // 获取长度
    LIST_APPEND,     // 列表追加元素
    DICT_SET,        // 字典设置键值对
    
    // 调试相关
    BREAKPOINT,      // 断点
    
    // 输入输出
    ECHO,            // 输出值
    
    // 结束
    HALT             // 停止执行
};

// 指令结构
struct Instruction {
    OpCode opcode;
    uint8_t a;       // 目标寄存器
    uint8_t b;       // 源寄存器1
    uint8_t c;       // 源寄存器2
    uint32_t bx;     // 常量池索引或跳转偏移
    
    Instruction() : opcode(OpCode::HALT), a(0), b(0), c(0), bx(0) {}
    
    Instruction(OpCode op, uint8_t reg_a = 0, uint8_t reg_b = 0, uint8_t reg_c = 0, uint32_t const_bx = 0)
        : opcode(op), a(reg_a), b(reg_b), c(reg_c), bx(const_bx) {}
    
    static Instruction load_const(uint8_t reg, uint32_t const_index);
    static Instruction binary_op(OpCode op, uint8_t dest, uint8_t left, uint8_t right);
    static Instruction jump(OpCode op, uint32_t offset);
    static Instruction call(uint8_t func_reg, uint8_t argc);
    static Instruction list_append(uint8_t list_reg, uint8_t value_reg);
    static Instruction dict_set(uint8_t dict_reg, uint8_t key_reg, uint8_t value_reg);
    
    std::string to_string() const;
};

// 行号映射
struct LineInfo {
    uint32_t bytecode_offset;
    uint32_t source_line;
    
    LineInfo(uint32_t offset, uint32_t line) 
        : bytecode_offset(offset), source_line(line) {}
};

using Bytecode = std::vector<Instruction>;
using LineMap = std::vector<LineInfo>;

// 添加to_string函数声明
std::string to_string(OpCode opcode);

} // namespace viml

#endif // VIML_INSTRUCTION_H